package com.hhit.zhgd.service.impl

import cn.afterturn.easypoi.excel.ExcelExportUtil
import cn.afterturn.easypoi.excel.ExcelImportUtil
import cn.afterturn.easypoi.excel.entity.ExportParams
import cn.afterturn.easypoi.excel.entity.ImportParams
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult
import cn.hutool.core.bean.BeanUtil
import cn.hutool.core.collection.CollUtil
import cn.hutool.core.map.MapUtil
import cn.hutool.core.util.StrUtil
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.baomidou.mybatisplus.core.metadata.IPage
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import com.hhit.zhgd.config.InitDictionaryConfig
import com.hhit.zhgd.dao.ZhgdEquipmentMaterialTestingMapper
import com.hhit.zhgd.domain.dto.BackStageEquipmentMaterialTestingDTO
import com.hhit.zhgd.domain.entity.ZhgdEquipmentMaterialTesting
import com.hhit.zhgd.domain.excelimport.EquipmentMaterialTestingImportParam
import com.hhit.zhgd.domain.response.BaseResp
import com.hhit.zhgd.enums.WitnessOrNotEnum
import com.hhit.zhgd.service.ZhgdEquipmentMaterialTestingService
import com.hhit.zhgd.utils.CustomExcelExportStyler
import jakarta.servlet.http.HttpServletResponse
import org.springframework.beans.BeanUtils
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.web.multipart.MultipartFile
import java.net.URLEncoder

@Service("zhgdEquipmentMaterialTestingService")
class ZhgdEquipmentMaterialTestingServiceImpl : ZhgdEquipmentMaterialTestingService,
    ServiceImpl<ZhgdEquipmentMaterialTestingMapper, ZhgdEquipmentMaterialTesting>() {

    @Transactional(rollbackFor = [Exception::class])
    override fun importEquipmentMaterialTesting(multipartFile: MultipartFile?): BaseResp<Any?>? {
        this.remove(QueryWrapper())
        val params = ImportParams()
        // 表头设置为1行
        params.headRows = 1
        val result: ExcelImportResult<EquipmentMaterialTestingImportParam?> =
            ExcelImportUtil.importExcelMore<EquipmentMaterialTestingImportParam>(
                multipartFile?.inputStream,
                EquipmentMaterialTestingImportParam::class.java, params
            )
        if (CollUtil.isNotEmpty(result.failList)) {
            for (equipmentMaterialTestingImportParam in result.failList) {
                val msg =
                    "第" + ((equipmentMaterialTestingImportParam?.getRowNum()
                        ?: 0) + 1) + "行的错误是：" + equipmentMaterialTestingImportParam?.errorMsg
                return BaseResp.fail("导入失败:$msg")
            }
        }
        val zhgdEquipmentMaterialTestings: MutableList<ZhgdEquipmentMaterialTesting> = CollUtil.newArrayList()
        for (equipmentMaterialTestingImportParam in result.getList()) {
            val zhgdEquipmentMaterialTesting = ZhgdEquipmentMaterialTesting()
            equipmentMaterialTestingImportParam?.witnessOrNot = java.lang.String.valueOf(
                WitnessOrNotEnum.fromMessage(
                    equipmentMaterialTestingImportParam?.witnessOrNot ?: ""
                )
            )
            equipmentMaterialTestingImportParam?.handInDrawingsFlag = java.lang.String.valueOf(
                WitnessOrNotEnum.fromMessage(
                    equipmentMaterialTestingImportParam?.handInDrawingsFlag ?: ""
                )
            )
            BeanUtil.copyProperties(equipmentMaterialTestingImportParam, zhgdEquipmentMaterialTesting)
            zhgdEquipmentMaterialTestings.add(zhgdEquipmentMaterialTesting)
        }
        val saveBatchRes = this.saveBatch(zhgdEquipmentMaterialTestings)
        return if (saveBatchRes) {
            BaseResp.success()
        } else {
            BaseResp.fail("导入设备材料检测计划数据失败!")
        }
    }

    @Transactional(rollbackFor = [Exception::class])
    override fun confirmEmtHandInDrawings(id: Int?): BaseResp<Any?>? {
        val zhgdEquipmentMaterialTesting = getById(id)
        zhgdEquipmentMaterialTesting.handInDrawingsFlag = 1
        val updateRes = updateById(zhgdEquipmentMaterialTesting)
        return if (updateRes) {
            BaseResp.success()
        } else {
            BaseResp.fail("修改交图状态失败!")
        }
    }

    @Transactional(rollbackFor = [Exception::class])
    override fun addEquipmentMaterialTesting(backStageEquipmentMaterialTestingDTO: BackStageEquipmentMaterialTestingDTO?): BaseResp<Any?>? {
        val zhgdEquipmentMaterialTesting = ZhgdEquipmentMaterialTesting()
        BeanUtils.copyProperties(backStageEquipmentMaterialTestingDTO!!, zhgdEquipmentMaterialTesting)
        val saveRes = save(zhgdEquipmentMaterialTesting)
        return if (saveRes) {
            BaseResp.success()
        } else BaseResp.fail("添加设备材料检测计划失败!")
    }

    @Transactional(rollbackFor = [Exception::class])
    override fun editEquipmentMaterialTesting(backStageEquipmentMaterialTestingDTO: BackStageEquipmentMaterialTestingDTO?): BaseResp<Any?>? {
        val zhgdEquipmentMaterialTesting = ZhgdEquipmentMaterialTesting()
        BeanUtils.copyProperties(backStageEquipmentMaterialTestingDTO!!, zhgdEquipmentMaterialTesting)
        val editRes = updateById(zhgdEquipmentMaterialTesting)
        return if (editRes) {
            BaseResp.success()
        } else BaseResp.fail("修改设备材料检测计划失败!")
    }

    @Transactional(rollbackFor = [Exception::class])
    override fun delEquipmentMaterialTesting(ids: List<Int?>?): BaseResp<Any?>? {
        if (CollUtil.isNotEmpty(ids)) {
            val delRes = this.removeByIds(ids)
            return if (delRes) {
                BaseResp.success()
            } else {
                BaseResp.fail("删除设备材料检测计划失败!")
            }
        }
        return BaseResp.fail("无可删除的编号!")
    }

    override fun getEquipmentMaterialTestingPageInfo(
        keyWord: String?,
        page: Int,
        size: Int
    ): IPage<BackStageEquipmentMaterialTestingDTO>? {
        val queryWrapper = QueryWrapper<ZhgdEquipmentMaterialTesting>()
        if (StrUtil.isNotBlank(keyWord)) {
            queryWrapper.like("test_item", keyWord)
                .or().like("specification", keyWord)
                .or().like("sample_number", keyWord)
                .or().like("sample_rate", keyWord)
                .or().like("part_used", keyWord)
        }
        val pageRequest = Page<ZhgdEquipmentMaterialTesting>(page.toLong(), size.toLong())
        val zhgdEquipmentMaterialTestingPage: IPage<ZhgdEquipmentMaterialTesting> = this.page(pageRequest, queryWrapper)
        // Convert to DTO
        val dtoList = zhgdEquipmentMaterialTestingPage.records
            .map { entity: ZhgdEquipmentMaterialTesting ->
                val dto = BackStageEquipmentMaterialTestingDTO()
                BeanUtils.copyProperties(entity, dto)
                dto.witnessOrNotName = MapUtil.getStr(
                    InitDictionaryConfig.DICTIONARY_MAP,
                    String.format("%s/%s", InitDictionaryConfig.WITNESS_OR_NOT_FLAG, entity.witnessOrNot),
                    StrUtil.EMPTY
                )
                dto.handInDrawingsFlagName = MapUtil.getStr(
                    InitDictionaryConfig.DICTIONARY_MAP,
                    String.format("%s/%s", InitDictionaryConfig.HAND_IN_DRAWINGS_FLAG, entity.witnessOrNot),
                    StrUtil.EMPTY
                )
                dto
            }.toCollection(ArrayList())
        val dtoPage: IPage<BackStageEquipmentMaterialTestingDTO> =
            Page(page.toLong(), size.toLong(), zhgdEquipmentMaterialTestingPage.total)
        dtoPage.setRecords(dtoList)
        return dtoPage
    }

    override fun exportEquipmentMaterialTesting(response: HttpServletResponse?) {
        val zhgdEquipmentMaterialTestings = this.list()
        val list: MutableList<BackStageEquipmentMaterialTestingDTO> = java.util.ArrayList()
        for (zhgdEquipmentMaterialTesting in zhgdEquipmentMaterialTestings) {
            val backStageEquipmentMaterialTestingDTO = BackStageEquipmentMaterialTestingDTO()
            BeanUtils.copyProperties(zhgdEquipmentMaterialTesting!!, backStageEquipmentMaterialTestingDTO)
            list.add(backStageEquipmentMaterialTestingDTO)
        }
        // 设计表头格式
        val equipmentMaterialTestingHeaderList: List<ExcelExportEntity>? = getExportRebateOffsetTableHeader()
        // 根据表头对应的key填充数据
        val equipmentMaterialTestingRecordList: List<Map<String, Any?>?>? = getExportRebateOffsetCallRecord(list)

        val exportParams = ExportParams(null, "")
        exportParams.type = ExcelType.HSSF
        exportParams.style = CustomExcelExportStyler::class.java
        // 根据表头和数据导出Excel
        val workbook = ExcelExportUtil.exportExcel(
            exportParams,
            equipmentMaterialTestingHeaderList,
            equipmentMaterialTestingRecordList
        )

        response!!.characterEncoding = "UTF-8"
        response!!.contentType = "application/vnd.ms-excel"
        response!!.setHeader(
            "Content-disposition",
            "attachment;filename=" + URLEncoder.encode(
                String.format(
                    "%s_%s.xls",
                    "设备材料检测计划",
                    System.currentTimeMillis()
                ), "UTF-8"
            )
        )
        workbook.write(response!!.outputStream)
        workbook.close()
    }


    private fun getExportRebateOffsetTableHeader(): List<ExcelExportEntity>? {
        // 表头设置
        val equipmentMaterialTestingHeaderList: MutableList<ExcelExportEntity> = java.util.ArrayList()
        val testItemEntity = ExcelExportEntity("检测项目", "testItem")
        equipmentMaterialTestingHeaderList.add(testItemEntity)
        val specificationEntity = ExcelExportEntity("规格", "specification")
        equipmentMaterialTestingHeaderList.add(specificationEntity)
        val sampleNumberEntity = ExcelExportEntity("取样数量", "sampleNumber")
        equipmentMaterialTestingHeaderList.add(sampleNumberEntity)
        val sampleRateEntity = ExcelExportEntity("取样频率", "sampleRate")
        equipmentMaterialTestingHeaderList.add(sampleRateEntity)
        val partUsedEntity = ExcelExportEntity("使用部位", "partUsed")
        equipmentMaterialTestingHeaderList.add(partUsedEntity)
        val witnessOrNotEntity = ExcelExportEntity("是否见证", "witnessOrNot")
        equipmentMaterialTestingHeaderList.add(witnessOrNotEntity)
        val handInDrawingsFlagEntity = ExcelExportEntity("是否交图", "handInDrawingsFlag")
        equipmentMaterialTestingHeaderList.add(handInDrawingsFlagEntity)
        return equipmentMaterialTestingHeaderList
    }

    private fun getExportRebateOffsetCallRecord(list: List<BackStageEquipmentMaterialTestingDTO>): List<Map<String, Any?>>? {
        val equipmentMaterialTestingRecordList: MutableList<Map<String, Any?>> = java.util.ArrayList()
        for (backStageEquipmentMaterialTestingDTO in list) {
            backStageEquipmentMaterialTestingDTO.let {
                val equipmentMaterialTestingRecordMap: MutableMap<String, Any?> = HashMap()
                equipmentMaterialTestingRecordMap["testItem"] = it.testItem
                equipmentMaterialTestingRecordMap["specification"] = it.specification
                equipmentMaterialTestingRecordMap["sampleNumber"] = it.sampleNumber
                equipmentMaterialTestingRecordMap["sampleRate"] = it.sampleRate
                equipmentMaterialTestingRecordMap["partUsed"] = it.partUsed
                equipmentMaterialTestingRecordMap["witnessOrNot"] =
                    if (it.witnessOrNot == null) "未知" else WitnessOrNotEnum.fromCode(
                        it.witnessOrNot!!
                    )
                equipmentMaterialTestingRecordMap["handInDrawingsFlag"] =
                    if (it.handInDrawingsFlag == null) "未知" else WitnessOrNotEnum.fromCode(
                        it.handInDrawingsFlag!!
                    )
                equipmentMaterialTestingRecordList.add(equipmentMaterialTestingRecordMap)
            }
        }
        return equipmentMaterialTestingRecordList
    }
}